home *** CD-ROM | disk | FTP | other *** search
/ HPAVC / HPAVC CD-ROM.iso / GBCOPIER.ZIP / GBREAD.ARJ / READ.C < prev    next >
C/C++ Source or Header  |  1995-11-06  |  15KB  |  590 lines

  1. #include <stdio.h>
  2. #include <conio.h>
  3. #include <time.h>
  4.  
  5. #define DELAY   delay(wait_delay)
  6.  
  7. /* Change those defines to match your compiler. */
  8. #define OUTPORT(port, val)      outp(port, val); DELAY
  9. #define INPORT(port)            inp(port)
  10.  
  11. #define CTRL    ctrl_port
  12. #define DATA    data_port
  13. #define STATUS  status_port
  14.  
  15. /*
  16.  * Bits for MUX (C B A):
  17.  *      ~AUTOFDXT ~SCLINT ~STROBE
  18.  * Bits in CTRL register (7..0):
  19.  *      N/A N/A N/A IRQEnable ~SCLINT INIT ~AUTOFDXT ~STROBE
  20.  */
  21.  
  22. #define MASK            0x00
  23. #define nSTROBE         0x01
  24. #define nAUTOFDXT       0x02
  25. #define INIT            0x04
  26. #define nSCLINT         0x08
  27.  
  28. /* CTRL MUX */
  29. #define GET_LOW         MASK | nAUTOFDXT | nSCLINT | nSTROBE
  30. #define GET_HIGH        MASK | nAUTOFDXT | nSCLINT
  31. #define LOW_ADDR        MASK | nAUTOFDXT           | nSTROBE
  32. #define HIGH_ADDR       MASK | nAUTOFDXT
  33. #define SET_DATA        MASK |             nSCLINT | nSTROBE
  34. #define DATA_REG        MASK |             nSCLINT
  35. #define NOT_USED        MASK |                       nSTROBE
  36. #define NOP             MASK
  37.  
  38. /* CTRL U3 */
  39. #define MREQ            MASK | INIT
  40.  
  41. /* Load a register: toggle CK (OFF and ON) */
  42. #define LOAD(reg)       OUTPORT(CTRL, reg); OUTPORT(CTRL, NOP)
  43.  
  44. /* Put data on the bus */
  45. #define WRITE(val)      OUTPORT(DATA, val)
  46.  
  47. /* Write data in bank-switch IC */
  48. #define WRITE_BKSW      WRITE(0x00); OUTPORT(CTRL, SET_DATA); \
  49.                         WRITE(0x01); WRITE(0x00); OUTPORT(CTRL, NOP)
  50.  
  51. /* Write data in RAM */
  52. #define WRITE_MEM       WRITE(0x00); OUTPORT(CTRL, SET_DATA); \
  53.                         OUTPORT(CTRL, SET_DATA | MREQ); WRITE(0x01); \
  54.                         WRITE(0x00); OUTPORT(CTRL, NOP)
  55.  
  56. /*
  57.  * Bits read (7..0):
  58.  *      BUSY ~ACKPR PE SLCT ERROR N/A N/A N/A
  59.  * Bits from REGISTER (D7..D4, D3..D0):
  60.  *      SLCT PE BUSY ~ACK
  61.  */
  62. #define READ_LOW(val)       OUTPORT(CTRL, GET_LOW); val = INPORT(STATUS)
  63. #define READ_HIGH(val)      OUTPORT(CTRL, GET_HIGH); val = INPORT(STATUS)
  64. #define READ_MEM_LOW(val)   OUTPORT(CTRL, GET_LOW | MREQ); val = INPORT(STATUS)
  65. #define READ_MEM_HIGH(val)  OUTPORT(CTRL, GET_HIGH | MREQ); val = INPORT(STATUS)
  66. #define D7(val)             (val & 0x10) << 3
  67. #define D6(val)             (val & 0x20) << 1
  68. #define D5(val)             ((val ^ 0x80) & 0x80) >> 2
  69. #define D4(val)             (val & 0x40) >> 2
  70. #define D3(val)             (val & 0x10) >> 1
  71. #define D2(val)             (val & 0x20) >> 3
  72. #define D1(val)             ((val ^ 0x80) & 0x80) >> 6
  73. #define D0(val)             (val & 0x40) >> 6
  74. #define CONVERT(l, h)       D7(h) | D6(h) | D5(h) | D4(h) | D3(l)  | D2(l)  | D1(l)  | D0(l)
  75.  
  76. #define NO_MBC  0
  77. #define MBC1    1
  78. #define MBC2    2
  79.  
  80. #ifdef MK_FP
  81.   #undef MK_FP
  82. #endif
  83. #define MK_FP(seg, ofs)     ((void far *) ((unsigned long) (seg)<<16|(ofs)))
  84.  
  85. char *type[] = {
  86.     "ROM ONLY", "ROM+MBC1", "ROM+MBC1+RAM", "ROM+MBC1+RAM+BATTERY",
  87.     "UNKNOWN", "ROM+MBC2", "ROM+MBC2+BATTERY"
  88. };
  89. int rom[] = { 32, 64, 128, 256, 512 };
  90. int ram[] = { 0, 2, 8, 32 };
  91. int mbc[] = { NO_MBC, MBC1, MBC1, MBC1, MBC2, MBC2 };
  92.  
  93. int wait_delay;
  94. unsigned ctrl_port;
  95. unsigned data_port;
  96. unsigned status_port;
  97.  
  98. void usage()
  99. {
  100.     printf("Usage: read [-p int] [-w int] [-t | -d | -a | -s file | -b file | -r file]\n");
  101.     printf("\t-p\tSpecify the port to use (default is 1 = LPT1)\n");
  102.     printf("\t-w\tSpecify the time to wait between accesses to the cartridge\n");
  103.     printf("\t-t\tDebug mode (if the cartridge reader don't work)\n");
  104.     printf("\t-t\tTest the cartridge reader\n");
  105.     printf("\t-a\tAnalyze the cartridge\n");
  106.     printf("\t-s\tSave the cartridge in a file\n");
  107.     printf("\t-b\tBackup the SRAM and save it in a file\n");
  108.     printf("\t-r\tRestore the SRAM from a file\n");
  109. }
  110.  
  111. int init_port(int port)
  112. {
  113.     data_port = *(unsigned far *)MK_FP(0x0040, 6 + 2*port);
  114.     if(data_port == 0)
  115.     {
  116.         printf("Can't find address of parallel port %d...\n", port);
  117.         exit(1);
  118.     } else {
  119.         status_port = data_port + 1;
  120.         ctrl_port = data_port + 2;
  121.         printf("Parallel port %d is located at %X-%X\n", port, data_port, ctrl_port);
  122.     }
  123. }
  124.  
  125. void delay(int i)
  126. {
  127.     while(i--);
  128. }
  129.  
  130. void read_data(FILE *fp, int type, int sizekB)
  131. {
  132.     int bank, page, byte, nbbank;
  133.     unsigned char low, high;
  134.  
  135.     /* One bank is 16k bytes */
  136.     nbbank = sizekB / 16;
  137.  
  138.     for(bank = 0; bank < nbbank; bank++) {
  139.         printf("Reading bank %d\n", bank);
  140.         if(bank) {
  141.             WRITE(bank);
  142.             LOAD(DATA_REG);
  143.             WRITE(0x21);
  144.             LOAD(HIGH_ADDR);
  145.             WRITE(0x00);
  146.             LOAD(LOW_ADDR);
  147.             WRITE_BKSW;
  148.         }
  149.         for(page = (bank ? 0x40 : 0); page < (bank ? 0x80 : 0x40); page++) {
  150.             printf(".");
  151.             WRITE(page);
  152.             LOAD(HIGH_ADDR);
  153.  
  154.             for(byte = 0; byte <= 0xFF; byte++) {
  155.                 WRITE(byte);
  156.                 LOAD(LOW_ADDR);
  157.  
  158.                 READ_LOW(low);
  159.                 READ_HIGH(high);
  160.                 fputc(CONVERT(low, high), fp);
  161.             }
  162.         }
  163.         printf("\n");
  164.     }
  165. }
  166.  
  167. void read_sram(FILE *fp, int type, int sizekB)
  168. {
  169.     int bank, page, byte, nbbank, banksize;
  170.     unsigned char low, high;
  171.  
  172.     if(type == MBC1) {
  173.         /* One bank is 8k bytes */
  174.         nbbank = sizekB / 8;
  175.         if(nbbank == 0) {
  176.             nbbank = 1;
  177.             banksize = sizekB << 2;
  178.         } else
  179.             banksize = 0x20;
  180.     } else {
  181.         /* SRAM is 512 * 4 bits */
  182.         nbbank = 1;
  183.         banksize = 0x02;
  184.     }
  185.  
  186.     /* Initialize the bank-switch IC */
  187.     WRITE(0x0A);
  188.     LOAD(DATA_REG);
  189.     WRITE(0x00);
  190.     LOAD(HIGH_ADDR);
  191.     WRITE(0x00);
  192.     LOAD(LOW_ADDR);
  193.     WRITE_BKSW;
  194.  
  195.     for(bank = 0; bank < nbbank; bank++) {
  196.         if(type == MBC1) {
  197.             printf("Reading bank %d\n", bank);
  198.             WRITE(bank);
  199.             LOAD(DATA_REG);
  200.             WRITE(0x40);
  201.             LOAD(HIGH_ADDR);
  202.             WRITE(0x00);
  203.             LOAD(LOW_ADDR);
  204.             WRITE_BKSW;
  205.         }
  206.         for(page = 0xA0; page < 0xA0 + banksize; page++) {
  207.             printf(".");
  208.             WRITE(page);
  209.             LOAD(HIGH_ADDR);
  210.  
  211.             for(byte = 0; byte <= 0xFF; byte++) {
  212.                 WRITE(byte);
  213.                 LOAD(LOW_ADDR);
  214.  
  215.                 READ_MEM_LOW(low);
  216.                 READ_MEM_HIGH(high);
  217.                 fputc(CONVERT(low, high), fp);
  218.             }
  219.         }
  220.         printf("\n");
  221.     }
  222. }
  223.  
  224. void write_sram(FILE *fp, int type, int sizekB)
  225. {
  226.     int bank, page, byte, nbbank, banksize;
  227.     unsigned char low, high;
  228.  
  229.     if(type == MBC1) {
  230.         /* One bank is 8k bytes */
  231.         nbbank = sizekB / 8;
  232.         if(nbbank == 0) {
  233.             nbbank = 1;
  234.             banksize = sizekB << 2;
  235.         } else
  236.             banksize = 0x20;
  237.     } else {
  238.         /* SRAM is 512 * 4 bits */
  239.         nbbank = 1;
  240.         banksize = 0x02;
  241.     }
  242.  
  243.     /* Initialize the bank-switch IC */
  244.     WRITE(0x0A);
  245.     LOAD(DATA_REG);
  246.     WRITE(0x00);
  247.     LOAD(HIGH_ADDR);
  248.     WRITE(0x00);
  249.     LOAD(LOW_ADDR);
  250.     WRITE_BKSW;
  251.  
  252.     for(bank = 0; bank < nbbank; bank++) {
  253.         if(type == MBC1) {
  254.             printf("Writing bank %d\n", bank);
  255.             WRITE(bank);
  256.             LOAD(DATA_REG);
  257.             WRITE(0x40);
  258.             LOAD(HIGH_ADDR);
  259.             WRITE(0x00);
  260.             LOAD(LOW_ADDR);
  261.             WRITE_BKSW;
  262.         }
  263.         for(page = 0xA0; page < 0xA0 + banksize; page++) {
  264.             printf(".");
  265.             WRITE(page);
  266.             LOAD(HIGH_ADDR);
  267.  
  268.             for(byte = 0; byte <= 0xFF; byte++) {
  269.                 if(feof(fp)) {
  270.                     printf("Unexpected EOF\n");
  271.                     exit(1);
  272.                 }
  273.                 WRITE(byte);
  274.                 LOAD(LOW_ADDR);
  275.                 WRITE(fgetc(fp));
  276.                 LOAD(DATA_REG);
  277.                 WRITE_MEM;
  278.             }
  279.         }
  280.         printf("\n");
  281.     }
  282. }
  283.  
  284. void read_header(unsigned char *h)
  285. {
  286.     int byte, index = 0;
  287.     unsigned char low, high;
  288.  
  289.     WRITE(0x01);
  290.     LOAD(HIGH_ADDR);
  291.  
  292.     for(byte = 0; byte < 0x50; byte++) {
  293.         WRITE(byte);
  294.         LOAD(LOW_ADDR);
  295.  
  296.         READ_LOW(low);
  297.         READ_HIGH(high);
  298.         h[index++] = CONVERT(low, high);
  299.     }
  300.     printf("Game name: %s\n", &h[0x34]);
  301.     printf("Cartridge type: %d(%s)\n", h[0x47], type[h[0x47]]);
  302.     printf("ROM size: %d(%d kB)\n", h[0x48], rom[h[0x48]]);
  303.     printf("RAM size: %d(%d kB)\n", h[0x49], ram[h[0x49]]);
  304. }
  305.  
  306. void test()
  307. {
  308.     int addr, errors;
  309.     unsigned char low, high;
  310.  
  311.     printf("Connect A0..A7 to D0..D7 and press <RETURN>\n");
  312.     getch();
  313.     for(addr = 0, errors = 0; addr < 0xFF; addr++) {
  314.         WRITE(addr);
  315.         LOAD(LOW_ADDR);
  316.         READ_LOW(low);
  317.         READ_HIGH(high);
  318.         if(CONVERT(low, high) != addr)
  319.             errors++;
  320.     }
  321.     printf("%d errors (%d%%)\n\n", errors, errors*100/0xFF);
  322.  
  323.     printf("Connect A8..A15 to D0..D7 and press <RETURN>\n");
  324.     getch();
  325.     for(addr = 0, errors = 0; addr < 0xFF; addr++) {
  326.         WRITE(addr);
  327.         LOAD(HIGH_ADDR);
  328.         READ_LOW(low);
  329.         READ_HIGH(high);
  330.         if(CONVERT(low, high) != addr)
  331.             errors++;
  332.     }
  333.     printf("%d errors (%d%%)\n\n", errors, errors*100/0xFF);
  334. }
  335.  
  336. void debug()
  337. {
  338.     int i = 0;
  339.  
  340.     printf("Check pins <3,4,7,8,13,14,17,18> of U2, U3 or U5\n");
  341.     OUTPORT(DATA, 0x00);
  342.     printf("They should all be low. Press <RETURN>\n");
  343.     getch();
  344.     OUTPORT(DATA, 0xFF);
  345.     printf("They should all be high. Press <RETURN>\n");
  346.     getch();
  347.     printf("End of test %d.\n\n", ++i);
  348.  
  349.     printf("Check pins <15,14,13,12,11,10,9,7> of U8\n");
  350.     OUTPORT(CTRL, GET_LOW);
  351.     printf("Pin 15 should be low, others should be high. Press <RETURN>\n");
  352.     getch();
  353.     OUTPORT(CTRL, GET_HIGH);
  354.     printf("Pin 14 should be low, others should be high. Press <RETURN>\n");
  355.     getch();
  356.     OUTPORT(CTRL, SET_DATA);
  357.     printf("Pin 13 should be low, others should be high. Press <RETURN>\n");
  358.     getch();
  359.     OUTPORT(CTRL, DATA_REG);
  360.     printf("Pin 12 should be low, others should be high. Press <RETURN>\n");
  361.     getch();
  362.     OUTPORT(CTRL, LOW_ADDR);
  363.     printf("Pin 11 should be low, others should be high. Press <RETURN>\n");
  364.     getch();
  365.     OUTPORT(CTRL, HIGH_ADDR);
  366.     printf("Pin 10 should be low, others should be high. Press <RETURN>\n");
  367.     getch();
  368.     OUTPORT(CTRL, NOT_USED);
  369.     printf("Pin 9 should be low, others should be high. Press <RETURN>\n");
  370.     getch();
  371.     OUTPORT(CTRL, NOP);
  372.     printf("Pin 8 should be low, others should be high. Press <RETURN>\n");
  373.     getch();
  374.     printf("End of test %d.\n\n", ++i);
  375.  
  376.     printf("Check pins <2,5,6,9,12,15,16,19> of U2\n");
  377.     WRITE(0x01);
  378.     LOAD(LOW_ADDR);
  379.     printf("Pin 2 should be high, others should be low. Press <RETURN>\n");
  380.     getch();
  381.     WRITE(0x02);
  382.     LOAD(LOW_ADDR);
  383.     printf("Pin 5 should be high, others should be low. Press <RETURN>\n");
  384.     getch();
  385.     WRITE(0x04);
  386.     LOAD(LOW_ADDR);
  387.     printf("Pin 6 should be high, others should be low. Press <RETURN>\n");
  388.     getch();
  389.     WRITE(0x08);
  390.     LOAD(LOW_ADDR);
  391.     printf("Pin 9 should be high, others should be low. Press <RETURN>\n");
  392.     getch();
  393.     WRITE(0x10);
  394.     LOAD(LOW_ADDR);
  395.     printf("Pin 12 should be high, others should be low. Press <RETURN>\n");
  396.     getch();
  397.     WRITE(0x20);
  398.     LOAD(LOW_ADDR);
  399.     printf("Pin 15 should be high, others should be low. Press <RETURN>\n");
  400.     getch();
  401.     WRITE(0x40);
  402.     LOAD(LOW_ADDR);
  403.     printf("Pin 16 should be high, others should be low. Press <RETURN>\n");
  404.     getch();
  405.     WRITE(0x80);
  406.     LOAD(LOW_ADDR);
  407.     printf("Pin 19 should be high, others should be low. Press <RETURN>\n");
  408.     getch();
  409.     printf("End of test %d.\n\n", ++i);
  410.  
  411.     printf("Check pins <2,5,6,9,12,15,16,19> of U3\n");
  412.     WRITE(0x01);
  413.     LOAD(HIGH_ADDR);
  414.     printf("Pin 2 should be high, others should be low. Press <RETURN>\n");
  415.     getch();
  416.     WRITE(0x02);
  417.     LOAD(HIGH_ADDR);
  418.     printf("Pin 5 should be high, others should be low. Press <RETURN>\n");
  419.     getch();
  420.     WRITE(0x04);
  421.     LOAD(HIGH_ADDR);
  422.     printf("Pin 6 should be high, others should be low. Press <RETURN>\n");
  423.     getch();
  424.     WRITE(0x08);
  425.     LOAD(HIGH_ADDR);
  426.     printf("Pin 9 should be high, others should be low. Press <RETURN>\n");
  427.     getch();
  428.     WRITE(0x10);
  429.     LOAD(HIGH_ADDR);
  430.     printf("Pin 12 should be high, others should be low. Press <RETURN>\n");
  431.     getch();
  432.     WRITE(0x20);
  433.     LOAD(HIGH_ADDR);
  434.     printf("Pin 15 should be high, others should be low. Press <RETURN>\n");
  435.     getch();
  436.     WRITE(0x40);
  437.     LOAD(HIGH_ADDR);
  438.     printf("Pin 16 should be high, others should be low. Press <RETURN>\n");
  439.     getch();
  440.     WRITE(0x80);
  441.     LOAD(HIGH_ADDR);
  442.     printf("Pin 19 should be high, others should be low. Press <RETURN>\n");
  443.     getch();
  444.     printf("End of test %d.\n\n", ++i);
  445.  
  446.     printf("Check pins <2,5,6,9,12,15,16,19> of U5\n");
  447.     WRITE(0x01);
  448.     LOAD(DATA_REG);
  449.     printf("Pin 2 should be high, others should be low. Press <RETURN>\n");
  450.     getch();
  451.     WRITE(0x02);
  452.     LOAD(DATA_REG);
  453.     printf("Pin 5 should be high, others should be low. Press <RETURN>\n");
  454.     getch();
  455.     WRITE(0x04);
  456.     LOAD(DATA_REG);
  457.     printf("Pin 6 should be high, others should be low. Press <RETURN>\n");
  458.     getch();
  459.     WRITE(0x08);
  460.     LOAD(DATA_REG);
  461.     printf("Pin 9 should be high, others should be low. Press <RETURN>\n");
  462.     getch();
  463.     WRITE(0x10);
  464.     LOAD(DATA_REG);
  465.     printf("Pin 12 should be high, others should be low. Press <RETURN>\n");
  466.     getch();
  467.     WRITE(0x20);
  468.     LOAD(DATA_REG);
  469.     printf("Pin 15 should be high, others should be low. Press <RETURN>\n");
  470.     getch();
  471.     WRITE(0x40);
  472.     LOAD(DATA_REG);
  473.     printf("Pin 16 should be high, others should be low. Press <RETURN>\n");
  474.     getch();
  475.     WRITE(0x80);
  476.     LOAD(DATA_REG);
  477.     printf("Pin 19 should be high, others should be low. Press <RETURN>\n");
  478.     getch();
  479.     printf("End of test %d.\n\n", ++i);
  480.  
  481.     printf("Check pins <3,6,8> of U7\n");
  482.     OUTPORT(CTRL, NOP | MREQ);
  483.     printf("Pin 6 should be low. Press <RETURN>\n");
  484.     getch();
  485.     OUTPORT(CTRL, NOP);
  486.     printf("Pin 6 should be high. Press <RETURN>\n");
  487.     getch();
  488.     OUTPORT(CTRL, SET_DATA);
  489.     printf("Pin 3 should be high, pin 8 should be low. Press <RETURN>\n");
  490.     getch();
  491.     OUTPORT(CTRL, NOP);
  492.     printf("Pin 3 should be low, pin 8 should be high. Press <RETURN>\n");
  493.     getch();
  494.     printf("End of test %d.\n\n", ++i);
  495.  
  496.     printf("Check pins <1,19> of U4\n");
  497.     OUTPORT(CTRL, NOP);
  498.     printf("Pin 1 and 19 should be high. Press <RETURN>\n");
  499.     getch();
  500.     OUTPORT(CTRL, GET_HIGH);
  501.     printf("Pin 1 should be low, pin 19 should be high. Press <RETURN>\n");
  502.     getch();
  503.     OUTPORT(CTRL, GET_LOW);
  504.     printf("Pin 1 should be high, pin 19 should be low. Press <RETURN>\n");
  505.     getch();
  506.     printf("End of test %d.\n\n", ++i);
  507.  
  508.     printf("If all tests passed and 'read -a' doesn't read correctly the header,\n");
  509.     printf("please e-mail me.\n");
  510. }
  511.  
  512. void main(int argc, char **argv)
  513. {
  514.     int arg;
  515.     FILE *fp;
  516.     unsigned char header[0x50];
  517.  
  518.     if(argc < 2) {
  519.         usage();
  520.         exit(1);
  521.     }
  522.  
  523.     wait_delay = 10;
  524.     init_port(1);
  525.  
  526.     for(arg = 1; arg < argc; arg++) {
  527.         if(argv[arg][0] != '-') {
  528.             usage();
  529.             exit(1);
  530.         }
  531.         switch(argv[arg][1]) {
  532.             case 'p':
  533.             case 'P':
  534.                 init_port(atoi(argv[++arg]));
  535.                 break;
  536.             case 'w':
  537.             case 'W':
  538.                 wait_delay = atoi(argv[++arg]);
  539.                 break;
  540.             case 'd':
  541.             case 'D':
  542.                 debug();
  543.                 break;
  544.             case 't':
  545.             case 'T':
  546.                 test();
  547.                 break;
  548.             case 'a':
  549.             case 'A':
  550.                 read_header(header);
  551.                 break;
  552.             case 's':
  553.             case 'S':
  554.                 if((fp = fopen(argv[++arg], "wb")) == NULL) {
  555.                     printf("Error opening file %s\n", argv[arg]);
  556.                     exit(1);
  557.                 }
  558.                 read_header(header);
  559.                 read_data(fp, mbc[header[0x47]], rom[header[0x48]]);
  560.                 fclose(fp);
  561.                 break;
  562.             case 'b':
  563.             case 'B':
  564.                 if((fp = fopen(argv[++arg], "wb")) == NULL) {
  565.                     printf("Error opening file %s\n", argv[arg]);
  566.                     exit(1);
  567.                 }
  568.                 read_header(header);
  569.                 read_sram(fp, mbc[header[0x47]], ram[header[0x49]]);
  570.                 fclose(fp);
  571.                 break;
  572.             case 'r':
  573.             case 'R':
  574.                 if((fp = fopen(argv[++arg], "rb")) == NULL) {
  575.                     printf("Error opening file %s\n", argv[arg]);
  576.                     exit(1);
  577.                 }
  578.                 read_header(header);
  579.                 write_sram(fp, mbc[header[0x47]], ram[header[0x49]]);
  580.                 fclose(fp);
  581.                 break;
  582.             default:
  583.                 usage();
  584.                 exit(1);
  585.         }
  586.     }
  587.     exit(0);
  588. }
  589.  
  590.